﻿Imports System.Drawing
Imports System.ComponentModel

Public Class ServerStatusControl
    Inherits Windows.Forms.ProgressBar

    Private _StatusText As String

    Dim UpdateLabelTimer As New Threading.Timer(New Threading.TimerCallback(AddressOf UpdateLabel), Nothing, 100, 100)

#Region "user32.dll"
    Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As UInt32, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
    Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr

    'Progressbar styles
    Public Const PBS_SMOOTHREVERSE As Integer = &H10
    Public Const PBST_NORMAL As Integer = &H1    'used with PBM_SETSTATE
    Public Const PBST_ERROR As Integer = &H2     'used with PBM_SETSTATE
    Public Const PBST_PAUSED As Integer = &H3    'used with PBM_SETSTATE
    'Progressbar messages
    Public Const PBM_SETSTATE As Integer = WM_USER + 16

    Public Const WM_USER As Integer = &H400
    Public Const WM_PAINT As Integer = &HF
#End Region

    <System.ComponentModel.Category("Appearance")> _
    Public Property StatusText As String
        Get
            Return _StatusText
        End Get
        Set(ByVal value As String)
            _StatusText = value
            Me.Invalidate()
        End Set
    End Property

    Private Sub UpdateLabel()
        Try
            Dim g As Graphics = Me.CreateGraphics
            Dim TextSize As SizeF = g.MeasureString(StatusText, New Font("Microsoft Sans Serif", 10))

            g.DrawString(StatusText, New Font("Microsoft Sans Serif", 10), Brushes.Black, (0.5 * Width) - (0.5 * TextSize.Width), (0.5 * Height) - (0.5 * TextSize.Height))

            g.Dispose()
        Catch
        End Try
    End Sub

    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        UpdateLabelTimer = Nothing
        Try
            MyBase.Dispose(disposing)
        Catch
        End Try
    End Sub

    Public Sub New()
        SendMessage(Me.Handle, PBM_SETSTATE, PBST_NORMAL, 0)
    End Sub

    Protected Overloads Overrides ReadOnly Property CreateParams() As CreateParams
        Get
            Dim cParams As CreateParams = MyBase.CreateParams
            'Allows for smooth transition even when progressbar value is subtracted
            cParams.Style = cParams.Style Or PBS_SMOOTHREVERSE
            Return cParams
        End Get
    End Property

    Public Enum States
        Normal
        [Error]
        Paused
    End Enum

    Private ps_ As States = States.Normal
    <Description("Gets or sets the ProgressBar state."), Category("Appearance"), DefaultValue(States.Normal)> _
        Public Property ProgressState() As States
        Get
            Return ps_
        End Get
        Set(ByVal value As States)
            ps_ = value
            SetState(ps_)
        End Set
    End Property

    Public Sub SetState(ByVal State As States)
        SendMessage(Me.Handle, PBM_SETSTATE, PBST_NORMAL, 0)
        'above required for values to be updated properly, but causes a slight flicker
        Select Case State
            Case States.Normal
                SendMessage(Me.Handle, PBM_SETSTATE, PBST_NORMAL, 0)
            Case States.[Error]
                SendMessage(Me.Handle, PBM_SETSTATE, PBST_ERROR, 0)
            Case States.Paused
                SendMessage(Me.Handle, PBM_SETSTATE, PBST_PAUSED, 0)
            Case Else
                SendMessage(Me.Handle, PBM_SETSTATE, PBST_NORMAL, 0)
        End Select
    End Sub

    Protected Overloads Overrides Sub WndProc(ByRef m As Message)
        ' Listen for operating system messages.
        Select Case m.Msg
            Case WM_PAINT
                'Paint event
                SetState(ps_)
                'Paint the progressbar properly
                Exit Select
        End Select
        MyBase.WndProc(m)
    End Sub
End Class
